package kubevirtsvc

import (
	"errors"
	"fmt"
	corev1 "gluenet/internal/agent/api/core/v1"
	v1 "gluenet/internal/agent/api/meta/v1"
	"strings"
)

func (svc *Service) CreateVirtualMachine(vm *corev1.KubeVirtVirtualMachine) (resp corev1.CommonResp) {
	if err := svc.createVirtualMachine(vm); err != nil {
		svc.logger.Errorf(err.Error())
		resp = corev1.NewCommonFailureResp(err.Error())
	} else {
		resp = corev1.NewCommonSuccessRespWithData(vm)
	}

	return
}

func (svc *Service) createVirtualMachine(vm *corev1.KubeVirtVirtualMachine) error {
	var err error

	if svc.objects.IsExist(vm.GluenetGuid, vm.GluenetKind) || svc.kd.IsNameSpaceExist(vm.GluenetGuid) {
		return errors.New("duplicated resource")
	}

	if err = svc.kd.CreateNameSpace(vm.GluenetGuid); err != nil {
		return fmt.Errorf("create namespace %s falied", vm.GluenetGuid)
	}

	if err = svc.kd.Apply(strings.NewReader(vm.Spec.Yaml), &v1.ApplyOptions{NameSpace: vm.GluenetGuid}); err != nil {
		return errors.New("apply yaml falied")
	}

	return svc.objects.Put(
		vm.GluenetGuid,
		vm.GluenetKind,
		&corev1.KubeVirtVirtualMachineObj{
			GluenetMeta: vm.GluenetMeta,
			Spec:        vm.Spec,
			Status:      corev1.Status{State: corev1.StatusReady},
		})
}

func (svc *Service) GetVirtualMachineObject(meta *corev1.GluenetMeta) corev1.CommonResp {
	obj, err := svc.objects.Get(meta.GluenetGuid, meta.GluenetKind)
	if err != nil {
		return corev1.NewCommonFailureResp(err.Error())
	}

	return corev1.NewCommonSuccessRespWithData(obj)
}

func (svc *Service) DeleteVirtualMachine(meta *corev1.GluenetMeta) corev1.CommonResp {

	obj, err := svc.objects.Get(meta.GluenetGuid, meta.GluenetKind)
	vm, ok := obj.(*corev1.KubeVirtVirtualMachineObj)

	if err != nil && !ok {
		goto ErrProcess
	} else {
		vm.Status.State = corev1.StatusTerminating
	}

	if err = svc.kd.Delete(strings.NewReader(vm.Spec.Yaml), &v1.DeleteOptions{NameSpace: meta.GluenetGuid}); err != nil {
		goto ErrProcess
	}

	if err = svc.kd.DeleteNameSpace(meta.GluenetGuid); err != nil {
		goto ErrProcess
	} else {
		vm.Status.State = corev1.StatusTerminated
	}

	if err = svc.objects.DeleteAll(meta.GluenetGuid); err != nil {
		goto ErrProcess
	}

	return corev1.NewCommonSuccessRespWithData(nil)

ErrProcess:
	vm.Status.State = corev1.StatusError
	svc.logger.Errorf(err.Error())
	return corev1.NewCommonFailureResp(err.Error())
}
